package com.skylink.gaea.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.NullNode;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @author wangzezhou
 * @date 2021/12/9
 */
@Slf4j
public final class JsonMapper {

  private static class Holder {
    private static volatile ObjectMapper objectMapper;

    static {
      objectMapper = new ObjectMapper();
      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
  }

  private JsonMapper() {
  }

  /**
   * Java 对象转换成 json 字符串
   *
   * @param object
   *
   * @return json 字符串
   */
  public static String toJsonString(Object object) {

    try {
      return Holder.objectMapper.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      log.error("java 对象转换成 json 字符串发生异常：" + object, e);
    }

    return "{}";
  }


  /**
   * java 对象转换成 JsonNode 对象
   *
   * @param object java 对象
   *
   * @return JsonNode 对象
   */
  public static JsonNode toJsonNode(Object object) {
    return Holder.objectMapper.valueToTree(object);
  }

  /**
   * json 字符串转成 JsonNode 对象
   *
   * @param jsonContent json 字符串
   *
   * @return JsonNode 对象
   */
  public static JsonNode toJsonNode(String jsonContent) {
    try {
      return Holder.objectMapper.readTree(jsonContent);
    } catch (JsonProcessingException e) {
      log.error("json 字符串转换成 JsonNode 对象异常：" + jsonContent, e);
    }

    return NullNode.getInstance();
  }

  /**
   * json 字符串转成 java 对象
   *
   * @param jsonContent json 字符串
   * @param clazz       java Class
   *
   * @return java 对象
   */
  public static <T> T toObject(String jsonContent, Class<T> clazz) {

    try {
      return Holder.objectMapper.readValue(jsonContent, clazz);
    } catch (JsonProcessingException e) {
      log.error("json 字符串转换成 java 对象发生异常：" + jsonContent, e);
    }

    return null;
  }

  /**
   * 字符输入流对象转成 java 对象
   *
   * @param in    字符输入流对象
   * @param clazz java Class
   *
   * @return java 对象
   */
  public static <T> T toObject(InputStream in, Class<T> clazz) {
    try {
      return Holder.objectMapper.readValue(in, clazz);
    } catch (IOException e) {
      log.error("字符输入流对象转成 java 对象发生异常" + clazz, e);
    }
    return null;
  }

  /**
   * 字符输入流对象转成 java 对象
   *
   * @param in      字符输入流对象
   * @param typeRef java 类引用
   *
   * @return java 对象
   */
  public static <T> T toObject(InputStream in, TypeReference<T> typeRef) {
    try {
      return Holder.objectMapper.readValue(in, typeRef);
    } catch (IOException e) {
      log.error("输入流对象转成 java 对象发生异常：" + typeRef.getType().getClass(), e);
    }
    return null;
  }

  /**
   * 字符串转换成 java 对象 list
   *
   * @param jsonContent json 字符串
   * @param clazz       java Class
   *
   * @return java 对象 list
   */
  public static <T> List<T> toObjects(String jsonContent, Class<T> clazz) {

    try {
      return Holder.objectMapper.readValue(jsonContent, new TypeReference<List<T>>() {});
    } catch (IOException e) {
      log.error("json 字符串转换成 java 类对象数组发生异常：" + clazz, e);
    }

    return null;
  }

  /**
   * 字符输入流对象转换成 java 对象 list
   *
   * @param in    字符输入流对象
   * @param clazz 要转换的 java Class
   *
   * @return 转换后的 java 对象 list
   */
  public static <T> List<T> toObjects(InputStream in, Class<T> clazz) {
    try {
      return Holder.objectMapper.readValue(in, new TypeReference<List<T>>(){ });
    } catch (IOException e) {
      log.error("输入流对象转换成 java 类对象数组发生异常" + clazz, e);
    }

    return null;
  }

  /**
   * JsonNode 对象转换成 java对象
   *
   * @param value JsonNode 对象
   * @param clazz java Class
   * @param <T>   要转换的对象类型
   *
   * @return java 对象
   */
  public static <T> T toObject(JsonNode value, Class<T> clazz) {
    return Holder.objectMapper.convertValue(value, clazz);
  }
}
